import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

public class TestFangkuai extends JPanel implements SwingConstants {

	private static final long serialVersionUID = 1L;

	public static int blockSize = 19;
	public static final int gap = 1;

	private Block[][] blockAry;

	private BlockSet blockSet;

	public TestFangkuai() {
		blockAry = new Block[20][10];
		Random random = new Random();
		BlockType[] blockTypes = BlockType.values();
		for (int r = 0; r < blockAry.length; r++) {
			for (int c = 0; c < blockAry[r].length; c++) {
				blockAry[r][c] = new Block(blockTypes[random.nextInt(3)], r, c);
			}
		}
		blockAry[0][0] = new Block(BlockType.gray, 0, 0);
		
		addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				int row = e.getY()/20;
				int col = e.getX()/20;
				blockSet = new BlockSet();
				searchFor(blockAry[row][col]);
				System.out.println("sinkable:"+blockSet.sinkable);
				blockSet.add(blockAry[row][col]);
				if(blockSet.sinkable){
					for(Block block:blockSet){
						BlockType bt = block.type;
						blockAry[block.row+1][block.col].type = bt;
						block.type = BlockType.gray;
					}
				}
				repaint();
			}
		});
	}

	@Override
	public void paint(Graphics g) {
		g.setColor(Color.gray);
		g.fillRect(0, 0, getWidth(), getHeight());
		for (int r = 0; r < blockAry.length; r++) {
			for (int c = 0; c < blockAry[r].length; c++) {
				Block b = blockAry[r][c];
				g.setColor(b.type.color);
				g.fillRect(blockSize * c + gap * (c + 1), blockSize * r + gap * (r + 1), blockSize, blockSize);
				if(b.mark){
					g.setColor(Color.gray);
					g.fillRect(blockSize * c + gap * (c + 1) + 8, blockSize * r + gap * (r + 1) +8, 4, 4);
				}
				b.searched = false;
				b.mark = false;
			}
		}
	}

	public void searchFor(Block block) {
		int r = block.row;
		int c = block.col;
		block.searched = true;
		block.mark = true;
		if(r>0)
			validate(block, blockAry[r - 1][c]);
		if (c < 9)
			validate(block, blockAry[r][c + 1]);
		if (r < 19) {
			validate(block, blockAry[r + 1][c]);
			blockSet.sinkable &= calcSinkable(block);
		}
		else
			blockSet.sinkable = false;
		if(c>0)
			validate(block,blockAry[r][c - 1]);
	}
	
	public void validate(Block from,Block to){
		if (!to.searched) {
			to.searched = true;
			if (to.type.equals(from.type)) {
				blockSet.add(to);
				to.mark = true;
				searchFor(to);
			}
		}
	}
	
	public boolean calcSinkable(Block block){
		if (block.row < 19) {
			Block under = blockAry[block.row + 1][block.col];
			return (under.type == block.type || under.type == BlockType.gray);
		} else
			return false;
	}

	public static void main(String[] args) {
		JFrame frame = new JFrame();
		JPanel panel = new TestFangkuai();
		panel.setPreferredSize(new Dimension(200, 400));
		frame.setContentPane(panel);
		frame.pack();
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
}

// ----------//
enum BlockType {
	green(Color.green), red(Color.red), gray(Color.gray);

	public final Color color;

	private BlockType(Color color) {
		this.color = color;
	}
}

// ----------//
class Block {
	BlockType type;
	boolean searched;
	int from;

	int col, row;
	
	boolean mark;

	public Block(BlockType type, int row, int col) {
		super();
		this.type = type;
		this.row = row;
		this.col = col;
	}

	public void reset() {
		from = SwingConstants.CENTER;
		searched = false;
	}
}

class BlockSet extends LinkedList<Block>{
	private static final long serialVersionUID = 1L;
	boolean sinkable = true;
	public BlockSet() {}
	
}
